﻿namespace Ex03.GarageLogic
{
    using System;
    using System.Collections.Generic;
    using System.Text;

    public class GarageLogic
    {
        #region Messages
        public static string s_PrintParameter = "{0}{1}";
        public static string s_EmptyLine = " ";
        private const string k_LicenseNotExists = @"The License doesn't exists in system.";
        private const string k_StateIsNotValid = @"The state is not valid.";
        private const string k_VehicleNotRechargeable = @"The vehicle is not rechargeable.";
        private const string k_VehicleIsNotFuel = @"The vehicle is not fuel engine.";
        #endregion

        #region Data Members
        private readonly Dictionary<string, GarageVehicle> r_GarageVehicleList;
        #endregion

        #region Constructors
        /// <summary>
        /// This constructor create dictionary to map driving license number to vehicle
        /// </summary>
        public GarageLogic()
        {
            r_GarageVehicleList = new Dictionary<string, GarageVehicle>();
        }
        #endregion

        #region Public Methods
        public static bool KeyFoundInDictionaryAndNotEmptyOrNull(Dictionary<string, string> i_Dictionary, string i_Key)
        {
            bool result = false;

            if (i_Dictionary.ContainsKey(i_Key) && i_Dictionary[i_Key] != string.Empty && i_Dictionary[i_Key] != null)
            {
                result = true;
            }

            return result;
        }

        public bool IsFoundInGarageByLicenseNumber(string i_LicenseNumber)
        {
            return r_GarageVehicleList.ContainsKey(i_LicenseNumber) && r_GarageVehicleList[i_LicenseNumber] != null;
        }

        public void AddNewGarageVehicle(string i_LicenseNumber, eVehicleType i_VehicleType, eEngineType i_EnergyType)
        {
                GarageVehicle newGarageVehicle = GarageVehicleFactory.CreateGarageVehicle(i_LicenseNumber, i_VehicleType, i_EnergyType);
                r_GarageVehicleList.Add(i_LicenseNumber, newGarageVehicle);
        }

        public List<string> GetNeededParamsToBeUpdateToGarageVehicle(string i_LicenseNumber)
        {
            List<string> result = new List<string>();

            ThrowExceptionIfVehicleNotFound(i_LicenseNumber);

            r_GarageVehicleList[i_LicenseNumber].GetClassParametersNeededToCreate(ref result);

            return result;
        }

        public bool SetNeededParamsToBeUpdateToGarageVehicle(string i_LicenseNumber, ref Dictionary<string, string> io_Parameters)
        {
            bool allParamsWereUpdated = false;

            ThrowExceptionIfVehicleNotFound(i_LicenseNumber);
            r_GarageVehicleList[i_LicenseNumber].SetClassByParameters(ref io_Parameters);
            allParamsWereUpdated = allParametersWereUpdated(io_Parameters);

            return allParamsWereUpdated;
        }

        public Dictionary<string, string> GetListOfGarageVehicles(bool i_FilterByState, eVehicleState i_StateToFilterBy)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();

            foreach (var pair in r_GarageVehicleList)
            {
                GarageVehicle garageVehicle = pair.Value;

                if (i_FilterByState.Equals(true))
                {
                    if (garageVehicle.VehicleState.Equals(i_StateToFilterBy))
                    {
                        result.Add(garageVehicle.LicenseNumber, garageVehicle.StringVehicleState);
                    }
                }
                else
                {
                    result.Add(garageVehicle.LicenseNumber, garageVehicle.StringVehicleState);
                }
            }

            return result;
        }

        public void ChangeVehicleStateByLicense(string i_LicenseNumber, eVehicleState i_NewState)
        {
            ThrowExceptionIfVehicleNotFound(i_LicenseNumber);
            ThrowExceptionIfStateDoesntExist(i_NewState);

            r_GarageVehicleList[i_LicenseNumber].VehicleState = i_NewState;
        }

        public void InflateToMaximum(string i_LicenseNumber)
        {
            if (IsFoundInGarageByLicenseNumber(i_LicenseNumber))
            {
                r_GarageVehicleList[i_LicenseNumber].InflateToMaximum();
            }
        }

        public List<string> GetGarageVehicleDetailsByLicenseNumber(string i_LicenseNumber)
        {
            List<string> result = new List<string>();

            ThrowExceptionIfVehicleNotFound(i_LicenseNumber);

            r_GarageVehicleList[i_LicenseNumber].GetAllDetails(ref result);

            return result;
        }

        public void RefuelVehicleByLicenseNumberAndEnergyAddition(string i_LicenseNumber, float i_FuelAddition, eFuelType i_FuelType)
        {
            ThrowExceptionIfVehicleNotFound(i_LicenseNumber);
            ThrowExceptionIfVehicleIsNotFuelEngine(i_LicenseNumber);
            r_GarageVehicleList[i_LicenseNumber].FillWithFuel(i_FuelType, i_FuelAddition);
        }

        public void RechargeElectricVehicleByLicenseNumberAndEnergyAddition(string i_LicenseNumber, float i_EnergyAddition)
        {
            ThrowExceptionIfVehicleNotFound(i_LicenseNumber);
            ThrowExceptionIfVehicleIsNotChargeable(i_LicenseNumber);
            r_GarageVehicleList[i_LicenseNumber].ChargeEnergySource(i_EnergyAddition);
        }
        #endregion

        #region Private Methods
        private bool allParametersWereUpdated(Dictionary<string, string> io_Parameters)
        {
            bool result = true;

            foreach (var pair in io_Parameters)
            {
                if (pair.Value != string.Empty)
                {
                    result = false;
                    break;
                }
            }

            return result;
        }

        private void ThrowExceptionIfVehicleNotFound(string i_LicenseNumber)
        {
            if (!IsFoundInGarageByLicenseNumber(i_LicenseNumber))
            {
                throw new ArgumentException(k_LicenseNotExists);
            }
        }

        private void ThrowExceptionIfStateDoesntExist(eVehicleState i_NewState)
        {
            if (!eVehicleState.IsDefined(typeof(eVehicleState), i_NewState))
            {
                throw new ArgumentException(k_StateIsNotValid);
            }
        }

        private void ThrowExceptionIfVehicleIsNotChargeable(string i_LicenseNumber)
        {
            if (!r_GarageVehicleList[i_LicenseNumber].Vehicle.IsRechargeable)
            {
                throw new ArgumentException(k_VehicleNotRechargeable);
            }
        }

        private void ThrowExceptionIfVehicleIsNotFuelEngine(string i_LicenseNumber)
        {
            if (!r_GarageVehicleList[i_LicenseNumber].Vehicle.IsFuelEngine)
            {
                throw new ArgumentException(k_VehicleIsNotFuel);
            }
        }
        #endregion
    }
}
